package com.laolang.pluto.framework.config.security.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.laolang.pluto.framework.config.security.filter.JwtFilter;
import com.laolang.pluto.framework.config.security.filter.SecurityAuthenticationFilter;
import com.laolang.pluto.framework.config.security.handler.LoginFailureHandler;
import com.laolang.pluto.framework.config.security.handler.LoginSuccessHandler;
import com.laolang.pluto.framework.config.security.service.TokenService;
import com.laolang.pluto.framework.config.security.service.UserDetailsServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @author laolang
 * @date 2021-08-06 22:42
 */
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserDetailsServiceImpl userDetailsService;
    private final ObjectMapper objectMapper;
    private final TokenService tokenService;
    private final JwtFilter jwtFilter;
    //private final CorsFilter corsFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // 禁用 csrf
                .csrf().disable()
                // 跨域支持
                .cors()
                .and()
                // 禁用 session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                //.antMatchers("/auth/login").permitAll()
                // 配置匿名访问
                .antMatchers(
                        // 登录
                        "/auth/login",
                        // tool
                        //"/tool/**",
                        // druid
                        "druid/**"
                ).anonymous()
                .anyRequest().authenticated()
                .and()
                .addFilterAt(securityAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .addFilterAfter(jwtFilter, UsernamePasswordAuthenticationFilter.class)
        ;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    private SecurityAuthenticationFilter securityAuthenticationFilter() throws Exception {
        SecurityAuthenticationFilter filter = new SecurityAuthenticationFilter(objectMapper);
        filter.setAuthenticationManager(authenticationManager());
        filter.setFilterProcessesUrl("/auth/login");
        filter.setAuthenticationSuccessHandler(new LoginSuccessHandler(tokenService));
        filter.setAuthenticationFailureHandler(new LoginFailureHandler());
        return filter;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    //@Bean
    //CorsConfigurationSource configurationSource(){
    //    CorsConfiguration corsConfiguration = new CorsConfiguration();
    //    corsConfiguration.addAllowedOrigin("*");
    //    corsConfiguration.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));
    //    corsConfiguration.setAllowedHeaders(Collections.singletonList("*"));
    //    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    //    source.registerCorsConfiguration("/**",corsConfiguration);
    //    return source;
    //}
}
